/***************************************************************************************
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
*
* NEMU is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*          http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
***************************************************************************************/

#include <ftrace.h>
#include "local-include/reg.h"
#include "local-include/csr.h"
#include <cpu/cpu.h>
#include <cpu/ifetch.h>
#include <cpu/decode.h>

#define R(i) gpr(i)
#define Mr vaddr_read
#define Mw vaddr_write

enum {
    TYPE_I, TYPE_U, TYPE_S, TYPE_J, TYPE_B, TYPE_R,
    TYPE_N, // none
};

#define src1R() do { *src1 = R(rs1); } while (0)
#define src2R() do { *src2 = R(rs2); } while (0)
#define immI() do { *imm = SEXT(BITS(i, 31, 20), 12); } while(0)
#define immU() do { *imm = SEXT(BITS(i, 31, 12), 20) << 12; } while(0)
#define immS() do { *imm = (SEXT(BITS(i, 31, 25), 7) << 5) | BITS(i, 11, 7); } while(0)
#define immJ() do { *imm = SEXT((BITS(i, 31, 31) << 20) | (BITS(i, 19, 12) << 12) | (BITS(i, 20, 20) << 11) | (BITS(i, 30, 21) << 1), 21); } while(0)
#define immB() do { *imm = SEXT((BITS(i, 31, 31) << 12) | (BITS(i, 7, 7) << 11) | (BITS(i, 30, 25) << 5) | (BITS(i, 11, 8) << 1), 13); } while(0)

static void decode_operand(Decode *s, int *dest, word_t *src1, word_t *src2, word_t *imm, int type) {
    uint32_t i = s->isa.inst.val;
    int rd  = BITS(i, 11, 7);
    int rs1 = BITS(i, 19, 15);
    int rs2 = BITS(i, 24, 20);
    *dest = rd;
    switch (type) {
        case TYPE_I: src1R();          immI(); break;
        case TYPE_U:                   immU(); break;
        case TYPE_S: src1R(); src2R(); immS(); break;
        case TYPE_J:                   immJ(); break;
        case TYPE_B: src1R(); src2R(); immB(); break;
        case TYPE_R: src1R(); src2R();       ; break;
    }
}

static int decode_exec(Decode *s) {
    int dest = 0;
    word_t src1 = 0, src2 = 0, imm = 0;
    word_t csr_zimm = ZEXT(BITS(s->isa.inst.val, 19, 15), 5);
    // 在 inst_fetch 中, 取指后 s->snpc += 4, 这里使用 s->snpc 更新 s->dnpc;
    // 而 s->pc 在运行当前指令前后保持不变, NEMUTRAP(halt_pc) 传入的是 s->pc
    s->dnpc = s->snpc;

#define INSTPAT_INST(s) ((s)->isa.inst.val)
#define INSTPAT_MATCH(s, name, type, ... /* execute body */ ) { \
    decode_operand(s, &dest, &src1, &src2, &imm, concat(TYPE_, type)); \
    __VA_ARGS__ ; \
}

    INSTPAT_START();

    /* ************************************************** U-type ************************************************** */
    /* lui rd, immediate; 		x[rd] = sext(immediate[31:12] << 12); 		Load Upper Immediate; 			U-type; */
    INSTPAT("??????? ????? ????? ??? ????? 01101 11", lui    , U, R(dest) = imm);
    /* auipc rd, immediate; 	x[rd] = pc + sext(immediate[31:12]<<12);	Add Upper Immediate to PC;		U-type; */
    INSTPAT("??????? ????? ????? ??? ????? 00101 11", auipc  , U, R(dest) = s->pc + imm);
    /* ************************************************** U-type ************************************************** */


    /* ************************************************** J-type ************************************************** */
    /* jal rd, offset;			x[rd] = pc+4; pc += sext(offset);			Jump and Link;					J-type; */
    INSTPAT("??????? ????? ????? ??? ????? 11011 11", jal    , J, R(dest) = s->pc + 4; s->dnpc = s->pc + imm; IFDEF(CONFIG_FTRACE, ftrace_inst_jal(s)););
    /* ************************************************** J-type ************************************************** */


    /* ************************************************** B-type ************************************************** */
    /* beq rs1, rs2, offset;	if (rs1 == rs2) pc += sext(offset);		Branch if Equal;							B-type; */
    INSTPAT("??????? ????? ????? 000 ????? 11000 11", beq    , B, if (src1 == src2) s->dnpc = s->pc + imm;);
    /* bne rs1, rs2, offset;	if (rs1 != rs2) pc += sext(offset);		Branch if Not Equal;						B-type; */
    INSTPAT("??????? ????? ????? 001 ????? 11000 11", bne    , B, if (src1 != src2) s->dnpc = s->pc + imm;);
    /* blt rs1, rs2, offset;	if (rs1 <s rs2) pc += sext(offset);		Branch if Less Than; 						B-type; */
    INSTPAT("??????? ????? ????? 100 ????? 11000 11", blt    , B, if (SLT(src1, src2))  s->dnpc = s->pc + imm;);
    /* bge rs1, rs2, offset;	if (rs1 >=s rs2) pc += sext(offset);	Branch if Greater Than or Equal;			B-type; */
    INSTPAT("??????? ????? ????? 101 ????? 11000 11", bge    , B, if (SGE(src1, src2)) s->dnpc = s->pc + imm;);
    /* bltu rs1, rs2, offset;	if (rs1 <u rs2) pc += sext(offset);		Branch if Less Than, Unsigned;				B-type; */
    INSTPAT("??????? ????? ????? 110 ????? 11000 11", bltu   , B, if (ULT(src1, src2))  s->dnpc = s->pc + imm;);
    /* bgeu rs1, rs2, offset; 	if (rs1 >=u rs2) pc += sext(offset);	Branch if Greater Than or Equal, Unsigned;	B-type; */
    INSTPAT("??????? ????? ????? 111 ????? 11000 11", bgeu   , B, if (UGE(src1, src2)) s->dnpc = s->pc + imm;);
    /* ************************************************** B-type ************************************************** */


    /* ************************************************** S-type ************************************************** */
    /* sd rs2, offset(rs1);		M[x[rs1] + sext(offset) = x[rs2][63:0];			Store Doubleword;		S-type; */
    INSTPAT("??????? ????? ????? 011 ????? 01000 11", sd     , S, Mw(src1 + imm, 8, src2));
    /* sw rs2, offset(rs1);		M[x[rs1] + sext(offset) = x[rs2][31:0];			Store Word;				S-type; */
    INSTPAT("??????? ????? ????? 010 ????? 01000 11", sw     , S, Mw(src1 + imm, 4, src2));
    /* sh rs2, offset(rs1);		M[x[rs1] + sext(offset) = x[rs2][15:0]; 		Store Halfword;			S-type; */
    INSTPAT("??????? ????? ????? 001 ????? 01000 11", sh     , S, Mw(src1 + imm, 2, src2));
    /* sb rs2, offset(rs1);		M[x[rs1] + sext(offset) = x[rs2][7:0];			Store Byte;				S-type; */
    INSTPAT("??????? ????? ????? 000 ????? 01000 11", sb     , S, Mw(src1 + imm, 1, src2));
    /* ************************************************** S-type ************************************************** */


    /* ************************************************** I-type ************************************************** */
    /* jalr rd, offset(rs1);	t=pc+4; pc=(x[rs1]+sext(offset))&~1; x[rd]=t;	Jump and Link Register;			I-type; */
    INSTPAT("??????? ????? ????? 000 ????? 11001 11", jalr   , I, uint64_t t = s->pc + 4; s->dnpc = (src1 + imm) & ~1; R(dest) = t; IFDEF(CONFIG_FTRACE, ftrace_inst_jalr(s)););

    /* lb rd, offset(rs1); 		x[rd] = sext(M[x[rs1]+sext(offset)][7:0]);		Load Byte; 						I-type; */
    INSTPAT("??????? ????? ????? 000 ????? 00000 11", lb     , I, R(dest) = SEXT(BITS(Mr(src1 + imm, 1), 7, 0), 8));
    /* lbu rd, offset(rs1); 	x[rd] = M[x[rs1] + sext(offset)][7:0];			Load Byte, Unsigned); 			I-type; */
    INSTPAT("??????? ????? ????? 100 ????? 00000 11", lbu    , I, R(dest) = ZEXT(BITS(Mr(src1 + imm, 1), 7, 0), 8));
    /* lh rd, offset(rs1); 		x[rd] = sext(M[x[rs1]+sext(offset)][15:0]);		Load Halfword;					I-type; */
    INSTPAT("??????? ????? ????? 001 ????? 00000 11", lh     , I, R(dest) = SEXT(BITS(Mr(src1 + imm, 2), 15, 0), 16));
    /* lhu rd, offset(rs1);		x[rd] = M[x[rs1] + sext(offset)][15:0];			Load Halfword, Unsigned;		I-type; */
    INSTPAT("??????? ????? ????? 101 ????? 00000 11", lhu    , I, R(dest) = ZEXT(BITS(Mr(src1 + imm, 2), 15, 0), 16));
    /* lw rd, offset(rs1);		x[rd] = sext(M[x[rs1]+sext(offset)][31:0]);		Load Word;						I-type; */
    INSTPAT("??????? ????? ????? 010 ????? 00000 11", lw     , I, R(dest) = SEXT(BITS(Mr(src1 + imm, 4), 31, 0), 32));
    /* lwu rd, offset(rs1);		x[rd] = M[x[rs1] + sext(offset)][31:0]; 		Load Word, Unsigned;			I-type; */
    INSTPAT("??????? ????? ????? 110 ????? 00000 11", lwu    , I, R(dest) = ZEXT(BITS(Mr(src1 + imm, 4), 31, 0), 32));
    /* ld rd, offset(rs1);		x[rd] = M[x[rs1] + sext(offset)][63:0];			Load Doubleword;				I-type; */
    INSTPAT("??????? ????? ????? 011 ????? 00000 11", ld     , I, R(dest) = Mr(src1 + imm, 8));

    /* addi rd, rs1, immediate;		x[rd] = x[rs1] + sext(immediate);				Add Immediate;				I-type; */
    INSTPAT("??????? ????? ????? 000 ????? 00100 11", addi   , I, R(dest) = src1 + imm);
    /* addiw rd, rs1, immediate;	x[rd]=sext((x[rs1]+sext(immediate))[31:0]);		Add Word Immediate;			I-type; */
    INSTPAT("??????? ????? ????? 000 ????? 00110 11", addiw  , I, R(dest) = SEXT(BITS(src1 + imm, 31, 0), 32));

    /* srli rd, rs1, shamt;		x[rd] = (x[rs1] >>u shamt);					Shift Right Logical Immediate;			I-type; */
    INSTPAT("000000? ????? ????? 101 ????? 00100 11", srli   , I, R(dest) = SRL(src1, imm));
    /* srliw rd, rs1, shamt;	x[rd] = sext(x[rs1][31:0] >>u shamt);		Shift Right Logical Word Immediate; 	I-type; */ //注意 x[rs1][31:0] 的语义 BITS选取后默认是无符号数
    INSTPAT("000000? ????? ????? 101 ????? 00110 11", srliw  , I, R(dest) = SEXT(SRL(BITS(src1, 31, 0), imm), 32));
    /* srai rd, rs1, shamt;		x[rd] = (x[rs1] >>s shamt);					Shift Right Arithmetic Immediate;		I-type; */
    INSTPAT("010000? ????? ????? 101 ????? 00100 11", srai   , I, R(dest) = SRA(src1, BITS(imm, 7, 0)));
    /* sraiw rd, rs1, shamt;	x[rd] = sext(x[rs1][31:0] >>s shamt);		Shift Right Arithmetic Word Immediate;	I-type; */
    INSTPAT("010000? ????? ????? 101 ????? 00110 11", sraiw  , I, R(dest) = SEXT(SRA(SEXT(BITS(src1, 31, 0), 32), BITS(imm, 7, 0)), 32));
    /* slli rd, rs1, shamt;		x[rd] = x[rs1] << shamt;					Shift Left Logical Immediate;			I-type; */
    INSTPAT("000000? ????? ????? 001 ????? 00100 11", slli   , I, R(dest) = src1 << imm);
    /* slliw rd, rs1, shamt;	x[rd] = sext((x[rs1] << shamt)[31:0]);		Shift Left Logical Word Immediate;		I-type; */
    INSTPAT("000000? ????? ????? 001 ????? 00110 11", slliw  , I, R(dest) = SEXT(BITS(src1 << imm, 31, 0), 32));

    /* slti rd, rs1, immediate;		x[rd] = (x[rs1] <s sext(immediate));	Set if Less Than Immediate;					I-type; */
    INSTPAT("??????? ????? ????? 010 ????? 00100 11", slti   , I, R(dest) = SLT(src1, imm));
    /* sltiu rd, rs1, immediate;	x[rd] = (x[rs1] <u sext(immediate));	Set if Less Than Immediate, Unsigned;		I-type; */
    INSTPAT("??????? ????? ????? 011 ????? 00100 11", sltiu  , I, R(dest) = ULT(src1, imm));

    /* xori rd, rs1, immediate;		x[rd] = x[rs1] ^ sext(immediate); 		Exclusive-OR Immediate;		I-type; */
    INSTPAT("??????? ????? ????? 100 ????? 00100 11", xori   , I, R(dest) = src1 ^ imm);
    /* ori rd, rs1, immediate;		x[rd] = x[rs1] | sext(immediate); 		OR Immediate;				R-type; */
    INSTPAT("??????? ????? ????? 110 ????? 00100 11", ori    , I, R(dest) = src1 | imm);
    /* andi rd, rs1, immediate;		x[rd] = x[rs1] & sext(immediate); 		And Immediate;				I-type; */
    INSTPAT("??????? ????? ????? 111 ????? 00100 11", andi   , I, R(dest) = src1 & imm);

    /* csrrc rd, csr, rs1;			t = CSRs[csr], CSRs[csr] = t &~x[rs1], x[rd] = t;	Control and Status Register Read and Clear;		I-type; */
    INSTPAT("??????? ????? ????? 011 ????? 11100 11", csrrs   , I, uint64_t t = CSR(imm); CSR(imm) = t &~src1; R(dest) = t);
    /* csrrs rd, csr, rs1;			t = CSRs[csr], CSRs[csr] = t | x[rs1], x[rd] = t;	Control and Status Register Read and Set;		I-type; */
    INSTPAT("??????? ????? ????? 010 ????? 11100 11", csrrs   , I, uint64_t t = CSR(imm); CSR(imm) = t | src1; R(dest) = t);
    /* csrrw rd, csr, rs1;	t = CSRs[csr], CSRs[csr] = x[rs1], x[rd] = t;		Control and Status Register Read and Write;		I-type; */
    INSTPAT("??????? ????? ????? 001 ????? 11100 11", csrrw   , I, uint64_t t = CSR(imm); CSR(imm) = src1;  R(dest) = t);

    /* csrrci rd, csr, rs1;			t = CSRs[csr], CSRs[csr] = t &~zimm, x[rd] = t;	Control and Status Register Read and Clear Immediate;		I-type; */
    INSTPAT("??????? ????? ????? 111 ????? 11100 11", csrrs   , I, uint64_t t = CSR(imm); CSR(imm) = t &~csr_zimm; R(dest) = t);
    /* csrrsi rd, csr, rs1;			t = CSRs[csr], CSRs[csr] = t | zimm, x[rd] = t;	Control and Status Register Read and Set Immediate;		I-type; */
    INSTPAT("??????? ????? ????? 110 ????? 11100 11", csrrs   , I, uint64_t t = CSR(imm); CSR(imm) = t | csr_zimm; R(dest) = t);
    /* csrrwi rd, csr, rs1;	        t = CSRs[csr], CSRs[csr] = zimm, x[rd] = t;		Control and Status Register Read and Write Immediate;		I-type; */
    INSTPAT("??????? ????? ????? 101 ????? 11100 11", csrrw   , I, uint64_t t = CSR(imm); CSR(imm) = csr_zimm;  R(dest) = t);

    /* ecall ;				RaiseException(EnvironmentCall) ;		I-type; */
    INSTPAT("0000000 00000 00000 000 00000 11100 11", ecall   , I, s->dnpc = isa_raise_intr(CAUSE_MACHINE_ECALL, s->pc); IFDEF(CONFIG_ETRACE, Log("ecall: mepc=" FMT_WORD ", " "mcause=" FMT_WORD, s->pc, CAUSE_MACHINE_ECALL)););

    /* ************************************************** I-type ************************************************** */


    /* ************************************************** R-type ************************************************** */
    /* add rd, rs1, rs2;		x[rd] = x[rs1] + x[rs2];				Add; 				R-type; */
    INSTPAT("0000000 ????? ????? 000 ????? 01100 11", add    , R, R(dest) = src1 + src2);
    /* addw rd, rs1, rs2;		x[rd] = sext((x[rs1]+x[rs2])[31:0]); 	Add Word;			R-type; */
    INSTPAT("0000000 ????? ????? 000 ????? 01110 11", addw   , R, R(dest) = SEXT(BITS(src1 + src2, 31, 0), 32));

    /* sub rd, rs1, rs2; 		x[rd] = x[rs1] − x[rs2]; 				Substract;			R-type; */
    INSTPAT("0100000 ????? ????? 000 ????? 01100 11", sub    , R, R(dest) = src1 - src2);
    /* subw rd, rs1, rs2;		x[rd] = sext((x[rs1]-x[rs2])[31: 0]) 	Substract Word;		R-type; */
    INSTPAT("0100000 ????? ????? 000 ????? 01110 11", subw   , R, R(dest) = SEXT(BITS(src1 - src2, 31, 0), 32));

    /* rem rd, rs1, rs2;		x[rd] = x[rs1] %s x[rs2];						Remainder; 					R-type; */
    INSTPAT("0000001 ????? ????? 110 ????? 01100 11", rem    , R, R(dest) = SREM(src1, src2));
    /* remu rd, rs1, rs2;		x[rd] = x[rs1] %u x[rs2];						Remainder, Unsigned;		R-type; */
    INSTPAT("0000001 ????? ????? 111 ????? 01100 11", remu   , R, R(dest) = UREM(src1, src2));
    /* remw rd, rs1, rs2;		x[rd] = sext(x[rs1][31:0] %s x[rs2][31:0]);		Remainder Word;				R-type; */
    INSTPAT("0000001 ????? ????? 110 ????? 01110 11", remw   , R, R(dest) = SEXT(SREM(SEXT(BITS(src1, 31, 0), 32), SEXT(BITS(src2, 31, 0), 32)), 32));
    /* remuw rd, rs1, rs2;		x[rd] = sext(x[rs1][31:0] %u x[rs2][31:0])		Remainder Word, Unsigned);	R-type */
    INSTPAT("0000001 ????? ????? 111 ????? 01110 11", remuw  , R, R(dest) = SEXT(UREM(ZEXT(BITS(src1, 31, 0), 32), ZEXT(BITS(src2, 31, 0), 32)), 32));

    /* div rd, rs1, rs2;		x[rd] = x[rs1] /s x[rs2];						Divide;						R-type; */
    INSTPAT("0000001 ????? ????? 100 ????? 01100 11", div    , R, R(dest) = SDIV(src1, src2));
    /* divu rd, rs1, rs2;		x[rd] = x[rs1] /u x[rs2];						Divide, Unsigned;			R-type; */
    INSTPAT("0000001 ????? ????? 101 ????? 01100 11", divu   , R, R(dest) = UDIV(src1, src2));
    /* divw rd, rs1, rs2;		x[rd] = sext(x[rs1][31:0] /s x[rs2][31:0]);		Divide Word;				R-type; */
    INSTPAT("0000001 ????? ????? 100 ????? 01110 11", divw   , R, R(dest) = SEXT(SDIV(SEXT(BITS(src1, 31, 0), 32), SEXT(BITS(src2, 31, 0), 32)), 32));
    /* divuw rd, rs1, rs2;		x[rd] = sext(x[rs1][31:0] /u x[rs2][31:0]);		Divide Word, Unsigned;		R-type; */
    INSTPAT("0000001 ????? ????? 101 ????? 01110 11", divuw  , R, R(dest) = SEXT(UDIV(ZEXT(BITS(src1, 31, 0), 32), ZEXT(BITS(src2, 31, 0), 32)), 32));

    /* mul rd, rs1, rs2;		x[rd] = x[rs1] * x[rs2];				Multiply;						R-type; */
    INSTPAT("0000001 ????? ????? 000 ????? 01100 11", mul     , R, R(dest) = src1 * src2);
    /* mulw rd, rs1, rs2;		x[rd] = sext((x[rs1]*x[rs2])[31: 0]);	Multiply Word); 				R-type; */
    INSTPAT("0000001 ????? ????? 000 ????? 01110 11", mulw    , R, R(dest) = SEXT(BITS(src1 * src2, 31, 0), 32));
    /* mulhu rd, rs1, rs2;		x[rd] = (x[rs1]𝑢 ×𝑢 x[rs2]𝑢) ≫𝑢XLEN;   Multiply High Unsigned);        R-type; */
    INSTPAT("0000001 ????? ????? 011 ????? 01100 11", mulhu   , R, R(dest) = ((__uint128_t)src1 * (__uint128_t)src2) >> 64);

    /* slt rd, rs1, rs2;		x[rd] = (x[rs1] <s x[rs2]);						Set if Less Than;				R-type; */
    INSTPAT("0000000 ????? ????? 010 ????? 01100 11", slt    , R, R(dest) = SLT(src1, src2));
    /* sltu rd, rs1, rs2; 		x[rd] = (x[rs1] <u x[rs2]); 					Set if Less Than, Unsigned; 	R-type; */
    INSTPAT("0000000 ????? ????? 011 ????? 01100 11", sltu   , R, R(dest) = ULT(src1, src2));

    /* sll rd, rs1, rs2; 		x[rd] = x[rs1] << x[rs2];						Shift Left Logical;				R-type; */
    INSTPAT("0000000 ????? ????? 001 ????? 01100 11", sll    , R, R(dest) = src1 << src2);
    /* sra rd, rs1, rs2; 		x[rd] = (x[rs1] >>s x[rs2]); 					Shift Right Arithmetic;			R-type; */
    INSTPAT("0100000 ????? ????? 101 ????? 01100 11", sra    , R, R(dest) = SRA(src1, BITS(src2, 7, 0)));
    /* srl rd, rs1, rs2; 		x[rd] = (x[rs1] >>u x[rs2]);					Shift Right Logical; 			R-type; */
    INSTPAT("0000000 ????? ????? 101 ????? 01100 11", srl    , R, R(dest) = SRL(src1, src2));

    /* sllw rd, rs1, rs2;		x[rd] = sext((x[rs1] << x[rs2][4:0])[31:0]);	Shift Left Logical Word;		R-type; */
    INSTPAT("0000000 ????? ????? 001 ????? 01110 11", sllw   , R, R(dest) = SEXT(BITS(src1 << BITS(src2, 4, 0), 31, 0), 32));
    /* sraw rd, rs1, rs2;		x[rd] = sext(x[rs1][31:0] >>s x[rs2][4:0]);		Shift Right Arithmetic Word;	R-type; */
    INSTPAT("0100000 ????? ????? 101 ????? 01110 11", sraw   , R, R(dest) = SEXT(BITS(SRA(SEXT(BITS(src1, 31, 0), 32), BITS(src2, 4, 0)), 31, 0), 32));
    /* srlw rd, rs1, rs2;		x[rd] = sext(x[rs1][31:0] >>u x[rs2][4:0]) 		Shift Right Logical Word		R-type; */
    INSTPAT("0000000 ????? ????? 101 ????? 01110 11", srlw   , R, R(dest) = SEXT(BITS(SRL(ZEXT(BITS(src1, 31, 0), 32), BITS(src2, 4, 0)), 31, 0), 32));

    /* xor rd, rs1, rs2; 		x[rd] = x[rs1] ^ x[rs2];			Exclusive-OR;				R-type; */
    INSTPAT("0000000 ????? ????? 100 ????? 01100 11", xor    , R, R(dest) = src1 ^ src2);
    /* or rd, rs1, rs2; 		x[rd] = x[rs1] | x[rs2];			OR;							R-type; */
    INSTPAT("0000000 ????? ????? 110 ????? 01100 11", or     , R, R(dest) = src1 | src2);
    /* and rd, rs1, rs2;		x[rd] = x[rs1] & x[rs2];			And;						R-type; */
    INSTPAT("0000000 ????? ????? 111 ????? 01100 11", and    , R, R(dest) = src1 & src2);

    /* mret;					Machine-mode Exception Return;		R-type; */
    INSTPAT("0011000 00010 00000 000 00000 11100 11", mret   , R, s->dnpc = cpu.csr.mepc.value; cpu.csr.mstatus.MIE = cpu.csr.mstatus.MPIE; cpu.csr.mstatus.MPIE = 1; cpu.csr.mstatus.MPP = 0b11; IFDEF(CONFIG_ETRACE, Log("mret: mepc=" FMT_WORD, cpu.csr.mepc.value);));

    /* ************************************************** R-type ************************************************** */

    INSTPAT("0000000 00001 00000 000 00000 11100 11", ebreak , N, s->dnpc = isa_raise_intr(CAUSE_EBREAK, s->pc), NEMUTRAP(s->pc, R(10))); // R(10) is $a0
    INSTPAT("??????? ????? ????? ??? ????? ????? ??", inv    , N, s->dnpc = isa_raise_intr(CAUSE_INVALID_INST, s->pc), INV(s->pc));

    INSTPAT_END();

    R(0) = 0; // reset $zero to 0

    return 0;
}

int isa_exec_once(Decode *s) {
    // 这里传入 snpc 的指针, 是为了能在取指后直接修改 snpc
    s->isa.inst.val = inst_fetch(&s->snpc, 4);
    return decode_exec(s);
}
